/* ** por compatibilidad se omiten tildes **
================================================================================
 TRABAJO PRACTICO 3 - System Programming - ORGANIZACION DE COMPUTADOR II - FCEN
================================================================================
*/

#include "defines.h"
#include "game.h"
#include "syscall.h"

#include "screen.h"



void print(const char* str, unsigned int fil, unsigned int col, unsigned short attr);

void imprimir_tablero(unsigned char * tablero);
void imprimir_estado_tareas(unsigned char * tablero);
void imprimir_puntaje(int * puntajes);
void imprimir_ganador(int * puntajes);
int  juego_terminado(unsigned char * tablero);
void actualizar_pantalla(unsigned char * tablero, int * puntajes);
void calcular_puntajes(unsigned char * tablero, int * puntajes);
void imprimir_fondo();
void inicializar_puntajes(int * puntajes);


void task() {
	/* Task 5 : Tarea arbitro */

    imprimir_fondo();
    syscall_iniciar();

	int puntajes[4];
	
	while(!juego_terminado((unsigned char*)TABLERO_ADDR)) {
		calcular_puntajes((unsigned char*)TABLERO_ADDR, puntajes);
        actualizar_pantalla((unsigned char*)TABLERO_ADDR, puntajes);
        
    }
    
    calcular_puntajes((unsigned char*)TABLERO_ADDR, puntajes);
    actualizar_pantalla((unsigned char*)TABLERO_ADDR, puntajes);
    imprimir_ganador(puntajes);
    syscall_terminar();
    print("Juego Terminado", 24, 20, C_FG_RED | C_BG_BLACK);
    
    while (TRUE) {}
}

void inicializar_puntajes(int * puntajes) {
	puntajes[0] = 0;
	puntajes[1] = 0;
	puntajes[2] = 0;
	puntajes[3] = 0;
}

void calcular_puntajes(unsigned char * tablero, int * puntajes) {

	unsigned char celda;
    int index; 
    int limit = TABLERO_FILS * TABLERO_COLS;

	inicializar_puntajes(puntajes);
    for(index = 0; index < limit; ++index)
    {
		celda = tablero[index];
		if (celda == JUG_1)
			puntajes[0]++;
		else if (celda == JUG_2)
			puntajes[1]++;
		else if (celda == JUG_3)
			puntajes[2]++;
		else if (celda == JUG_4)
			puntajes[3]++;
		else
			continue;		// no tiene color
	}
}

void actualizar_pantalla(unsigned char * tablero, int * puntajes) {
	imprimir_tablero(tablero);
	imprimir_estado_tareas(tablero);
	imprimir_puntaje(puntajes);
}

void imprimir_estado_tareas(unsigned char* tablero) {
	print("Tarea 1: ", FILA_ESTADO_TAREA_1, 2, C_FG_BLUE);
	print("Tarea 2: ", FILA_ESTADO_TAREA_2, 2, C_FG_BROWN);
	print("Tarea 3: ", FILA_ESTADO_TAREA_3, 2, C_FG_GREEN);
	print("Tarea 4: ", FILA_ESTADO_TAREA_4, 2, C_FG_MAGENTA);


}
int juego_terminado(unsigned char * tablero) {
    int index; 
    int limit = TABLERO_FILS * TABLERO_COLS;
    int lleno = TRUE;
    
    for(index = 0; index < limit && lleno; ++index)
		lleno &= (tablero[index] != TABLERO_CELDA_VACIA);
		
	return lleno;
}

char * itoa(int n, char * s)
{
    char * dest = s;

    if(n / 10 != 0)
        dest = itoa(n/10, dest);
    else if(n < 0)
        *dest++ = '-';

    *dest++ = (n % 10) + '0';
    *dest = '\0';

    return dest;
}


void imprimir_ganador(int * puntajes) {
	int columna_inicial = 45;
	print("Tarea ganadora: x  Puntaje: ", 10, columna_inicial, C_FG_LIGHT_GREY);
	
	char numero[5], tarea[5];
	int ganador = 0;
	if (puntajes[ganador] < puntajes[1])
		ganador = 1;
	if (puntajes[ganador] < puntajes[2])
		ganador = 2;
	if (puntajes[ganador] < puntajes[3])
		ganador = 3;
			
	itoa(ganador + 1, tarea);
	print(tarea, 10, columna_inicial + 16, C_FG_LIGHT_GREY);
	
	int puntajeGanador = puntajes[ganador];
	itoa(puntajeGanador, numero);
	//print("     ", 8, 78, C_BG_CYAN);	// limpiamos la pantalla
	print(numero, 10, columna_inicial + 28, C_FG_LIGHT_GREY);
}



void imprimir_puntaje(int * puntajes) {
	char numero[4] = {0};
	int columnaInicial = 45;
	
	print("Puntaje Jugador 1 : ", 5, columnaInicial, C_BG_BLUE);
	numero[0] = 0, numero[1] = 0, numero[2] = 0, numero[3] = 0;
	itoa(puntajes[0], numero);
	print("     ", 5, columnaInicial + 22, C_BG_CYAN);	// limpiamos la pantalla
	print(numero, 5, columnaInicial + 22, C_BG_BLUE);
	
	print("Puntaje Jugador 2 : ", 6, columnaInicial, C_BG_BROWN);
	numero[0] = 0, numero[1] = 0, numero[2] = 0, numero[3] = 0;
	itoa(puntajes[1], numero);
	print("     ", 6, columnaInicial + 22, C_BG_CYAN);	// limpiamos la pantalla
	print(numero, 6, columnaInicial + 22, C_BG_BROWN);
	
	print("Puntaje Jugador 3 : ", 7, columnaInicial, C_BG_GREEN);
	numero[0] = 0, numero[1] = 0, numero[2] = 0, numero[3] = 0;
	itoa(puntajes[2], numero);
	print("     ", 7, columnaInicial + 22, C_BG_CYAN);	// limpiamos la pantalla
	print(numero, 7, columnaInicial + 22, C_BG_GREEN);
	
	print("Puntaje Jugador 4 : ", 8, columnaInicial, C_BG_MAGENTA);
	numero[0] = 0, numero[1] = 0, numero[2] = 0, numero[3] = 0;
	itoa(puntajes[3], numero);
	print("     ", 8, columnaInicial + 22, C_BG_CYAN);	// limpiamos la pantalla
	print(numero, 8, columnaInicial + 22, C_BG_MAGENTA);
}

void imprimir_tablero(unsigned char * tablero) {

    unsigned char (*tablero_m)[TABLERO_COLS] = (unsigned char (*)[TABLERO_COLS]) tablero;
    int fila_inicial = 2;
    int col_inicial = 1;
    int f;
	int c;
    
	for(f = 0; f < TABLERO_FILS; f++) {
		for(c = 0; c < TABLERO_COLS; c++) {
			char valor = tablero_m[f][c];
            
            int attrs = C_BG_BLACK;
            if (valor == JUG_1)
                attrs = C_BG_BLUE;
            if (valor == JUG_2)
                attrs = C_BG_BROWN;
            if (valor == JUG_3)
                attrs = C_BG_GREEN;
            if (valor == JUG_4)
                attrs = C_BG_MAGENTA;
            
            print(" ", fila_inicial +f, col_inicial + c, attrs);
            
		}
	}    
}

void imprimir_fondo() {
    int fila = 1;
    
    while (fila < 24) {
        const char* fondo_str = "                                                                                ";
        print (fondo_str, fila, 0, C_BG_CYAN);
        fila += 1;
    }
}

void print(const char* str, unsigned int fil, unsigned int col, unsigned short attr) {
	// Sugerencia: Implementar esta funcion que imprime en pantalla el string
	// *str* en la posicion (fil, col) con los atributos attr y usarla para
	// implementar todas las demas funciones que imprimen en pantalla.
    
    unsigned char* pantalla = (unsigned char*) VIDEO_ADDR;
    unsigned int string_index = 0;
    while (str[string_index] != 0) {
        char caracter = str[string_index];

        pantalla[fil * VIDEO_COLS * 2 + col * 2 + string_index * 2] = caracter;
        pantalla[fil * VIDEO_COLS * 2 + col * 2 + string_index * 2 + 1] = attr;
        
        string_index++;
    }
}
